<template>
  <div
    class="di-chart-container di-3dPie-chart__bg"
    :style="{ width: w + 'px', height: h + 'px' }"
    :ref="ref"
    @mouseenter="enter"
    @mouseleave="leave"
  ></div>
</template>

<script>
import _lo from "lodash";

import * as am4core from "@amcharts/amcharts4/core";
import * as am4charts from "@amcharts/amcharts4/charts";
import am4themes_animated from "@amcharts/amcharts4/themes/animated";

export default {
  compType: "图表",
  text: "C20210023饼图",
  name: "Chart23",
  components: {},
  mixins: [],
  data() {
    return {
      ref: `chart-3dPie`,
      chart: null,
      timer: null,
      //接受数据
      chartData: [
        { type: "办公", num: 22, color: "#397BFF" },
        { type: "工业", num: 44, color: "#FFE877" },
        { type: "住宅", num: 22, color: "#13EB9C" },
        { type: "商业", num: 22, color: "#946df8" },
        { type: "其他", num: 34, color: "#F2F4FF" },
      ],
      /*可配置的参数属性*/
      defaultConfig: {
        autoAni: false,
        depth: 30,
        angle: 46,
        radius: "100%",
        series: [
          {
            dataFields: {
              value: "num",
              category: "type",
            },
            tooltip: {
              label: {
                fontSize: 20,
              },
            },
            labels: {
              text: "{category}\n{value}\n{value.percent.formatNumber('#.0')}%",
              radius: 25,
              fontSize: 18,
            },
          },
        ],
      },
      mergedConfig: null,
      /*用于向外抛出option*/
      // localOption: null
    };
  },
  computed: {
    changeWH() {
      const { w, h } = this;
      return { w, h };
    },
  },
  watch: {
    accessData: {
      handler(newV) {
        this.chartData = newV;
        this.updateComponent(this.chartData);
      },
      immediate: true,
      deep: true,
    },
    config() {
      //接收属性
      this.mergeConfig();
      this.updateComponent(this.chartData);
    },
    changeWH() {
      this.autoResizeMixinInit();
    },
  },
  props: {
    // 组件宽度
    w: {
      type: [Number, String],
    },
    // 组件高度
    h: {
      type: [Number, String],
    },
    config: {
      type: Object,
      default: () => ({}),
    },
    accessData: {
      type: [Object, Array],
      default: () => [],
    },
  },
  created() {},
  mounted() {
    this.mergeConfig();
    this.initComponent();
  },
  methods: {
    initComponent() {
      let option = this.getOption(this.chartData);
      am4core.useTheme(am4themes_animated);

      this.chart && this.chart.dispose() && (this.chart = null);

      this.chart = am4core.createFromConfig(
        option,
        this.$refs[this.ref],
        am4charts.PieChart3D
      );
      this.chart.logo.scale = 0;

      this.chartAni();
    },
    getOption(data) {
      if (!data) return;
      let rgm = new am4core.RadialGradientModifier();
      rgm.opacities.push(0.88, 0.9, 0.95);
      rgm.lightnesses.push(0.1, 0.9, 0.3);
      rgm.brightnesses.push(-0.4, -0.2, 0.7);
      let dataColor = data.map((item) => item.color).filter((c) => !!c);
      let colorList = dataColor;
      let hideLabel = true;
      let option = _lo.merge(
        {
          hiddenState: {
            properties: {
              depth: 0,
              opacity: 0,
              // endAngle :-90
            },
            transitionDuration: 2000,
            transitionEase: am4core.ease.circleOut,
          },
          data: data,
          depth: 45,
          angle: 55,
          radius: "100%",
          // labelLine: {
          //   length: 10,
          //   length2: 20
          // },
          //innerRadius: "0%",
          series: [
            {
              type: "PieSeries3D",
              // hiddenState: {
              //   properties: {
              //     radius :am4core.percent(0)
              //   },
              //   transitionDuration: 5000,
              //   transitionEase: am4core.ease.circleOut
              // },
              colors: {
                list: colorList,
              },
              dataFields: {
                value: "num",
                category: "type",
              },
              // alignLabels: true,
              tooltip: {
                // show:true,
                label: {
                  fontSize: 30,
                },
              },
              labels: {
                hidden: hideLabel,
                // draggable:true,
                // maxWidth: rem2px(200),
                wrap: true,
                // html: '<p class="title">{category}</p><p class="num" style="color: #F2F4FF;font-family: digital;text-shadow: 0px 0px 24px rgba(242, 244, 255, 0.8); font-size: 0.24rem;"><span>{value.value}</span><span style="display:inline-block;padding-left: 0.15rem">{value.percent.formatNumber(\'#.0\')}%</span></p>',
                // text:"{value.percent.formatNumber('#.0')}%",
                text: "{category}\n{value}万人\n{value.percent.formatNumber('#.0')}%",
                // fill: '#fff',
                fontSize: 25,
                // paddingTop: 0,
                // paddingBottom: 0,
                radius: 35, //控制label距离中心点远近
                adapter: {
                  fill: (color, target) => {
                    return colorList[target.dataItem.index];
                  },
                },
              },
              states: {
                active: {
                  properties: {
                    scale: 1,
                    shiftRadius: 0.2,
                  },
                },
              },
              ticks: {
                hidden: hideLabel,
                stroke: "#ffffff",
                strokeOpacity: 1,
                strokeWidth: 1,
                // length:rem2px(50),
                //strokeDasharray: "10,6",
                strokeLinecap: "square",
                adapter: {
                  stroke: (color, target) => {
                    return colorList[target.dataItem.index];
                  },
                },
              },
              slices: {
                stroke: "#d6d1ec",
                strokeWidth: 0,
                strokeOpacity: 1,
                template: {
                  tooltipText:
                    "{category}\n{value}\n{value.percent.formatNumber('#.0')}%",
                  fillModifier: rgm,
                  fillOpacity: 0.95,
                  strokeModifier: rgm,
                  strokeOpacity: 0.1,
                  strokeDashoffset: 100,
                  strokeWidth: 2,
                  cornerRadius: 30,
                },
                states: {
                  hover: {
                    properties: {
                      scale: 1,
                      shiftRadius: 0.1,
                    },
                  },
                },
              },
            },
          ],
          autoDispose: true,
        },
        this.mergedConfig
      );

      //赋值给组件变量，用于外部引用,因为echarts的getOption得到的所有的配置有点冗余
      // this.localOption = option

      return option;
    },
    chartAni() {
      if (!this.chart.autoAni) return;
      if (this.timer) clearInterval(this.timer);
      // 设置actvie状态
      let _this = this;
      let pieSeries = this.chart.series.getIndex(0);
      let i = 0;
      let prevItem = null;

      function restoreSelected() {
        pieSeries.slices.each((slice, index) => {
          if (i == index) {
            slice.setState("active");
            if (prevItem) {
              prevItem.setState("default");
            }
            prevItem = slice;
          }
        });
        i++;
        let len = pieSeries.slices.length;
        if (i > len - 1) {
          i = 0;
        }
      }

      _this.timer = setInterval(restoreSelected, 4000);
      _this.$once("hook:beforeDestroy", function () {
        clearInterval(_this.timer);
      });
    },
    enter() {
      clearInterval(this.timer);
      let pieSeries = this.chart.series.getIndex(0);
      pieSeries.slices.each((slice) => {
        slice.setState("default");
      });
    },
    leave() {
      this.chartAni();
    },
    mergeConfig(paramConfig = {}) {
      const { defaultConfig, config } = this;
      this.mergedConfig = _lo.merge(
        {},
        defaultConfig,
        paramConfig,
        config || {}
      );
    },
    afterAutoResizeMixinInit() {
      this.initComponent();
    },
    /*
     * @vuese
     * 更新组件事件
     * @arg chartData=[{ type: '其他1', num: 22}]
     */
    updateComponent({ chartData }) {
      let option = this.getOption(chartData || this.chartData);
      this.chart && this.chart.dispose();
      // this.mychart.reinit()
      this.chart = am4core.createFromConfig(
        option,
        this.$refs[this.ref],
        am4charts.PieChart3D
      );
      this.chart.logo.scale = 0;
      this.chartAni();
    },
    destroyComponent() {
      this.chart && this.chart.dispose();
      clearInterval(this.timer);
      delete this.chart;
    },
  },
  beforeDestroy() {
    this.destroyComponent();
  },
};
</script>
<style lang="scss" scoped>
.di-3dPie-chart__bg {
  position: relative;
  perspective: 1000px;
  perspective-origin: bottom;

  &:before {
    z-index: 1;
    left: 50%;
    top: 50%;
    content: "";
    display: block;
    background-size: contain;
    width: 100%;
    height: 100%;
    position: absolute;
    background-image: url("~@a/imgs/commonIcons/circle-bg-big.png");
    background-position: center;
    background-repeat: no-repeat;
    background-size: auto 130%;
    transform-origin: 50% 50%;
    //transform: translate(-50%, -52%) rotateX(45deg) scale(1.2);
    animation: rotateAni2 20s linear infinite;
  }
}
</style>
<style lang="scss">
.di-3dPie-chart__bg {
  div {
    z-index: 10;
  }

  svg {
    z-index: 10;
  }
}

@keyframes rotateAni2 {
  from {
    transform: translate(-50%, -52%) rotateX(48deg) scale(1.2) rotateZ(0deg);
  }
  to {
    transform: translate(-50%, -52%) rotateX(48deg) scale(1.2) rotateZ(-360deg);
  }
}
</style>
